<template>
    <!-- 领标编辑 -->
    <div class="uploader">

        <!-- 上传中 -->
        <div class="uploading" v-if="uploader" :error="error ? 'error' : ''">
            <figure>
                <img v-if="uploader.image" :src="uploader.image.src"
                     :style="$fiexImage(uploader.image.width, uploader.image.height, 1)">
                <img v-else-if="error" class="uploader-error" src="@/assets/images/error.png">
                <UxLoading v-else />
            </figure>
            <div class="uploading-error" v-if="error">
                <span>Upload failed</span>
                <button @click="start()">Reupload</button>
            </div>

            <div class="uploading-percent" v-else>
                <el-progress type="circle" color="#ea4c89" :percentage="uploader.percent" :width="80" />
            </div>

        </div>

        <!-- 等待中 -->
        <div class="waiting" v-else-if="value">
            <figure><img :src="$getImageUrl(value, 'largest')"></figure>
            <span @click="doPreview()"><svg-icon name="user-files-preview" /></span>
            <em @click="doRemove()"><svg-icon name="dialog-close-full" /></em>
        </div>

        <div class="empty" v-else @click="start()">
            <!-- <img src="@/assets/images/user-unlogin.png" alt=""> -->
            <svg-icon name="upload-card" />
            <strong>Upload</strong>
            <span>JPG or PNG format Max 10 MB</span>
        </div>

        <UxImagePreview v-model="preview" />

    </div>

</template>
<script>
export default {
    name: "UserUploader",
    props: {
        folder: { type: String, require: false, default: 'upload' },
        value: { type: String, require: false, default: '' },
    },
    data () {
        return {
            uploader: null,
            error: null,
            preview: null,
        };
    },
    methods: {

        // 选中文件上传
        selectFile (callback) {

            let filebox = document.querySelector('.filebox');
            let input = null;

            if (filebox) {
                input = filebox.querySelector('input');
            } else {
                filebox = document.createElement('div');
                filebox.setAttribute('class', 'filebox');
                filebox.setAttribute('style', ' position: absolute;left: 0;top: 0;width: 0;height: 0;overflow: hidden;opacity: 0;');
                filebox.innerHTML = '<input type="file" accept="image/jpeg,image/jpg,image/png">';
                document.body.appendChild(filebox);
                input = filebox.querySelector('input');
            }


            input.onchange = () => {

                if (input.files && input.files[0]) {
                    let file = input.files[0];
                    let maxsize = 1024 * 1024 * 10; // 不能上传超过50M的图片
                    if (file.size > maxsize) {
                        // 图片过大
                        this.$uxMessage.error('Upload failed, file size exceeds 10MB.');
                    } else {
                        callback(file)
                    }
                } else {

                }
                input.lock = true;
                input.value = null;
                filebox.remove();
                // filebox.innerHTML = html;
            }

            // window.addEventListener('focus', focusEvent)
            input.click();
        },

        getFileMime (option) {
            return new Promise((resolve, reject) => {

                let blob = option.file.slice(0, 128);//仅获取前128字节。
                let reader = new FileReader();
                reader.onloadend = function (e) {
                    let arr = (new Uint8Array(e.target.result)).subarray(0, 200);
                    let header = "";
                    const mime = [//type:类型，h：16字节标识【根据需要，自行添加】
                        { type: 'image/png', h: '89504e47' },
                        { type: 'image/gif', h: '47494638' },
                        { type: 'image/jpeg', h: 'ffd8ffe0,ffd8ffe1,ffd8ffe2,ffd8ffe3,ffd8ffe8' },
                        { type: 'image/webp', h: '524946461c' },
                        { type: 'Windows Bitmap/bmp', h: '424D' },
                        { type: 'TIFF/tif', h: '49492A00' },
                        { type: 'CAD/dwg', h: '41433130' },
                        { type: 'Adobe Photoshop/psd', h: '384250' },
                    ]
                    const check = (header) => {
                        for (let i in mime) {
                            let arr = mime[i].h.split(',');
                            let offset = (mime[i].offset || -1) + 1;//偏移量
                            for (let j in arr) {
                                let byte = arr[j].toLowerCase().replace(/\s+/g, "");
                                if (header.indexOf(byte) == offset) {
                                    return mime[i].type;
                                }
                            }
                        }
                        return 'unknown';
                    }


                    for (let i = 0; i < arr.length; i++) {
                        header += arr[i].toString(16);
                    }

                    option.mime = check(header);
                    option.suffix = option.mime.replace(/^[\w\W]*\/(\w+)/, '$1')

                    if (/(png|jpe?g)$/i.test(option.suffix)) {
                        resolve(option)
                    } else {
                        reject('Upload failed, file format is incorrect.')
                    }
                }
                reader.readAsArrayBuffer(blob);
            })

        },

        getFilePreview (option) {
            return new Promise((resolve, reject) => {
                const _URL = window.URL || window.webkitURL;
                const img = new Image();
                img.onload = () => {
                    option.image = img;
                    resolve(option);
                };
                img.onerror = (error) => { reject(String(error)) };
                img.src = _URL.createObjectURL(option.file);
            })
        },


        uploadFile (option) {

            // 先上传大图
            // 再生成缩略图

            // 文件名
            if (!option.name) {
                const time = new Date().getTime();
                const random = Math.random().toFixed(10).substr(2);
                option.name = time + "-" + random + "." + option.suffix;
            } else {
                option.name = option.name.replace('{type}', option.suffix);
            }

            // 文件路径
            if (!option.path) {
                option.path = "data/zx/design/file/"
            }

            return new Promise((resolve, reject) => {

                // 递归循环上传，最多上次3次，太多次没有作用
                let count = 3;
                let doUpload = () => {
                    const request = {
                        file: option.file,
                        name: option.name,
                        path: option.path.replace(/\/+$/, '') + '/',
                        onprogress (event) {
                            option.percent = 5 + parseInt(0.9 * event.percent);
                            option.client = event.client;
                            option.cpt = event.cpt;
                        },
                    };

                    this.$uploadToOSS(request, response => {
                        if (response.code === 0 && response.data) {
                            option.url = response.data || '';
                            resolve(option);
                        } else if (--count < 0) {
                            reject("Upload failed, please check your network connection.");
                        } else if (this.uploader && this.uploader == option) {
                            setTimeout(() => doUpload(), 500);
                        } else {
                            // 新的上传
                        }
                    })
                };
                doUpload();
            });
        },

        // 开始上传
        startUpload (opt, callback) {

            this.selectFile((file) => {

                const option = {
                    path: opt.path || '', // 文件保存路径
                    name: opt.name || '', // 文件保存的名称
                    file: file, // 文件
                    mime: '', // 媒体类型
                    suffix: '', // 后缀名
                    image: null, // 预览地址
                    percent: 5, // 上传进度
                    url: '', // 上传完成后最终路径
                    thumb: '', // 生成的缩略图
                    client: null, // oss引用
                    cpt: null, // 分片上传引用
                    status: 'getinfo', // 当前状态 getinfo|upload|thumb|success|error
                }

                this.error = null;
                this.uploader = option;

                // 获取文件
                this.getFileMime(option).then(option => {
                    // 获取图片信息
                    if (this.uploader && this.uploader == option) {
                        return this.getFilePreview(option)
                    } else {
                        return Promise.reject('Uploader is cancel')
                    }
                }).then(option => {

                    // 上传图片
                    if (this.uploader && this.uploader == option) {
                        option.status = 'upload';
                        return this.uploadFile(option);
                    } else {
                        return Promise.reject('Uploader is cancel')
                    }

                }).then(option => {
                    // 上传成功
                    if (this.uploader && this.uploader == option) {
                        option.status = 'success';
                        callback && callback(option);
                    } else {
                        return Promise.reject('Uploader is cancel')
                    }
                }).catch(error => {

                    if (this.uploader && this.uploader == option) {
                        // 选择时如果不选中，则直接关闭
                        this.error = true;
                        this.$uxMessage.error(error);
                        this.close();
                    } else if (this.uploader) {
                        // 有新的上传
                    } else {
                        this.close();
                    }
                })
            })

        },

        doPreview () {
            this.preview = {
                index: 0,
                images: [this.$getImageUrl(this.value)]
            }
        },

        // 删除
        doRemove () {
            this.$emit('input', '')
            this.$emit('change', '')
        },

        close () {
            this.uploader = null;
            this.error = null;
        },

        // 取消上传
        cancel () {
            if (this.uploader && this.uploader.client && this.uploader.cpt) {
                this.uploader.client.abortMultipartUpload(this.uploader.cpt.name, this.uploader.cpt.uploadId)
                this.uploader.client = null;
                this.uploader.cpt = null;
            }
            this.close();
        },

        // 上传
        start () {
            this.startUpload({
                path: this.folder,
                name: new Date().getTime() + '.{type}',
            }, (res) => {
                this.$uxMessage.success('Upload successful');
                this.$emit('input', res.url)
                this.$emit('change', res.url)
                this.close()
            })
        }

    }
};
</script>
<style lang="scss" scoped>
.filebox {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    overflow: hidden;
    opacity: 0;
}

.uploader {
    z-index: 1;
    position: relative;

    &::before {
        content: '';
        display: block;
        padding-bottom: 100%;
    }

    .uploading,
    .waiting,
    .empty {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        border-radius: 8px;
    }


    .uploading {

        // h3 {
        //     margin-top: 14px;
        //     width: 100%;
        //     overflow: hidden;
        //     text-overflow: ellipsis;
        //     white-space: nowrap;
        //     text-align: center;
        //     font-size: 14px;
        //     font-family: Roboto-Regular, Roboto;
        //     font-weight: 400;
        //     color: #000000;
        //     line-height: 16px;
        // }

        &>figure {
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            border-radius: 8px;
            overflow: hidden;

            img {
                position: absolute;
                left: 0;
                top: 0;
                width: 100%;
                height: 100%;

                &.uploader-error {
                    width: 88px;
                    height: 88px;
                    left: 50%;
                    top: 50%;
                    transform: translate(-50%, -50%);
                }
            }
        }

        .uploading-error {
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            border-radius: 8px;
            background: rgba(192, 19, 23, 0.8);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            box-sizing: border-box;
            padding: 8px;

            span {
                font-family: Roboto, Roboto;
                font-weight: 500;
                font-size: 14px;
                color: #FFFFFF;
                line-height: 18px;
            }

            button {
                width: 100px;
                height: 28px;
                margin-top: 14px;
                box-sizing: border-box;
                background: #FFFFFF;
                border-radius: 6px;
                font-family: Roboto, Roboto;
                font-weight: 400;
                font-size: 14px;
                color: #000000;
                border: none;
            }
        }

        .uploading-percent {
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            border-radius: 8px;
            background-color: rgba(50, 50, 50, 0.5);
            display: flex;
            align-items: center;
            justify-content: center;

            &::v-deep .el-progress__text {
                font-family: Roboto, Roboto;
                font-weight: 400;
                font-size: 18px !important;
                color: #FFFFFF !important;
                line-height: 28px;
            }
        }
    }

    .waiting {
        cursor: pointer;
        border: 1px solid #e6e6e6;

        figure {
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;

            img {
                position: absolute;
                left: 0;
                top: 0;
                max-width: 100%;
                max-height: 100%;
                left: 50%;
                top: 50%;
                transform: translate(-50%, -50%);
            }
        }

        &>span {
            position: absolute;
            right: 7px;
            bottom: 7px;
            width: 30px;
            height: 30px;
            transition: all 0.2s;
            cursor: pointer;
            display: none;
            color: #f6f6f6;


            svg {
                width: 100%;
                height: 100%;
            }

            &:hover {
                color: #929292;
            }
        }

        &>em {
            position: absolute;
            right: -7px;
            top: -7px;
            width: 14px;
            height: 14px;
            background: #E0E0E0;
            border-radius: 20px;
            display: flex;
            align-items: center;
            justify-content: center;

            svg {
                width: 8px;
                height: 8px;
            }

            &:hover {
                background: #DE2F2F;
                color: #fff;
            }
        }

        &:hover {
            &>span {
                display: block;
            }
        }
    }

    .empty {
        padding: 10px;
        cursor: pointer;
        background: #f8f8f8;
        border: 1px dashed #b3b3b3;
        border-radius: 8px;


        svg {
            width: 20px;
            height: 18px;
            color: #292929;
        }

        strong {
            font-family: Roboto-Medium, Roboto;
            font-weight: 500;
            font-size: 12px;
            color: #757575;
            line-height: 14px;
            text-align: center;
            margin-top: 12px;
        }

        span {
            font-family: Roboto, Roboto;
            font-weight: 400;
            font-size: 12px;
            color: #9E9E9E;
            line-height: 16px;
            margin-top: 8px;
            text-align: center;
        }

        &:hover {
            border: 1px dashed #239AC2;
            background: rgba(237, 251, 255, 0.4);

            strong,
            span,
            svg {
                color: #239AC2;
            }
        }

    }
}
</style>
